#include "ITest.h"
#include "Test.h"

#include <string>
#include <vector>
#include <errno.h>
#include <iostream>

std::string TestDir = "TestModules";

#ifdef WIN32
#include <windows.h>

const char PathSep = '\\';

const char* LibraryExt = ".dll";

std::vector<std::string > IterateTestDir()
{
	std::vector<std::string > files;
	std::string path = ".\\";
	path += TestDir;
	path += "\\*";
	WIN32_FIND_DATAA file;
	HANDLE handle;
	handle = FindFirstFileA(path.c_str(), &file);
	if (handle)
	{
		do
		{
			if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{
				files.push_back((TestDir + PathSep) + file.cFileName);
			}
		} while (FindNextFileA(handle, &file) != 0);
	}
	else
	{
		printf("Could not open directory for iterating. Error code: %d\n", GetLastError());
	}
	return files;
}

#else
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

const char PathSep = '/';

const char* LibraryExt = ".so";

bool IsDir(std::string path)
{
	DIR* dir = opendir(path.c_str());
	bool ret = false;
	if (dir)
	{
		ret = true;
		closedir(dir);
	}
	return ret;
}

std::vector<std::string > IterateTestDir()
{
	std::vector<std::string > files;
	std::string path = "./";
	path += TestDir;
	DIR* dir = opendir(path.c_str());
	if (!dir)
	{
		fprintf(stderr, "IteratorTestDir: Could not open directory. Error code: %d\n", errno);
		return files;
	}
	dirent* file = NULL;
	path += "/";
	while ((file = readdir(dir)) != NULL)
	{
		if (!IsDir(path + file->d_name))
		{
			files.push_back(path + file->d_name);
		}
	}
	closedir(dir);
	return files;
}

#endif

std::vector<ITest*> GetTests()
{
	std::vector<std::string > files = IterateTestDir();
	std::vector<ITest*> tests;
	if (files.size() == 0)
	{
		fprintf(stderr, "GetTests: Error getting contents of Tests directory. Please ensure it exists and contains files.\n");
		return tests;
	}
	std::vector<std::string >::iterator iter = files.begin();
	ITest* test;
	Module* mod;
	int len, extLen = strlen(LibraryExt), pos = 0;
	for (; iter != files.end(); iter++)
	{
		len = (*iter).length();
		pos = (*iter).find(LibraryExt);
		if (pos == len - extLen)
		{
			mod = new Module(*iter);
			test = new Test(mod);
			tests.push_back(test);
		}
	}
	return tests;
}

int main(int argc, const char** argv)
{
	std::vector<ITest*> tests = GetTests();
	std::vector<ITest*>::iterator testIter = tests.begin();
	TestInfo* info;
	bool good = false;
	FILE* file = fopen("failed-tests.txt", "w");
	for (; testIter != tests.end(); testIter++)
	{
		if (*testIter == NULL)
		{
			printf("*testIter == NULL\n");
			continue;
		}
		info = (*testIter)->GetTestInfo();
		if (info)
		{
			printf("Running test: `%s`\n", info->Name.c_str());
			good = (*testIter)->Run();
			if (good)
			{
				printf("Test ran correctly\n");
			}
			else
			{
				printf("Test did not run correctly\n");
				fprintf(file, "`%s` in %s\n", info->Name.c_str(), info->File.c_str());
			}
		}
		else
		{
			printf("GetTestInfo=NULL\n");
		}
	}
	fclose(file);
	std::cin.get();
	return 0;
}
